home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
051-075
/
068
/
mg1b
/
match.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-13
|
5KB
|
222 lines
/*
* Name: MicroEMACS
* Limited parenthesis matching routines
* Version: Gnu30
* Last edit: 13-Jul-86
* Created: 19-May-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
*
* The hacks in this file implement automatic matching
* of (), [], {}, and other characters. It would be
* better to have a full-blown syntax table, but there's
* enough overhead in the editor as it is.
*
* Since I often edit Scribe code, I've made it possible to
* blink arbitrary characters -- just bind delimiter characters
* to "blink-matching-paren-hack"
*/
#include "def.h"
static int balance();
static displaymatch();
/* Balance table. When balance() encounters a character
* that is to be matched, it first searches this table
* for a balancing left-side character. If the character
* is not in the table, the character is balanced by itself.
* This is to allow delimiters in Scribe documents to be matched.
*/
static struct balance {
char left, right;
} bal[] = {
{ '(', ')' },
{ '[', ']' },
{ '{', '}' },
{ '<', '>' },
{ '\0','\0'}
};
/*
* Fake the GNU "blink-matching-paren" variable.
* If the argument exists, nonzero means show,
* zero means don't. If it doesn't exist,
* pretend it's nonzero.
*/
blinkparen(f, n, k)
{
register char *command;
register SYMBOL *sp;
if (f == FALSE)
n = 1;
command = (n == 0) ? "self-insert-command" :
"blink-matching-paren-hack";
if ((sp=symlookup(command)) == NULL) {
ewprintf("blinkparen: no binding for %s",command);
return (FALSE);
}
binding[(KEY) ')'] = sp; /* rebind paren */
return (TRUE);
}
/*
* Self-insert character, then show matching character,
* if any. Bound to "blink-matching-paren-command".
*/
showmatch(f, n, k)
{
register int i, s;
if (k == KRANDOM)
return(FALSE);
for (i = 0; i < n; i++) {
if ((s = selfinsert(f, 1, k)) != TRUE)
return(s);
if (balance(k) != TRUE) /* unbalanced -- warn user */
ttbeep();
}
return (TRUE);
}
/*
* Search for and display a matching character.
*
* This routine does the real work of searching backward
* for a balancing character. If such a balancing character
* is found, it uses displaymatch() to display the match.
*/
static balance(k)
int k;
{
register LINE *clp;
register int cbo;
int c;
int i;
int rbal, lbal;
int depth;
rbal = k & KCHAR;
if ((k&KCTRL)!=0 && rbal>='@' && rbal<='_') /* ASCII-ify. */
rbal -= '@';
/* See if there is a matching character -- default to the same */
lbal = rbal;
for (i = 0; bal[i].right != '\0'; i++)
if (bal[i].right == rbal) {
lbal = bal[i].left;
break;
}
/* Move behind the inserted character. We are always guaranteed */
/* that there is at least one character on the line, since one was */
/* just self-inserted by blinkparen. */
clp = curwp->w_dotp;
cbo = curwp->w_doto - 1;
depth = 0; /* init nesting depth */
for (;;) {
if (cbo == 0) { /* beginning of line */
clp = lback(clp);
if (clp == curbp->b_linep)
return (FALSE);
cbo = llength(clp)+1;
}
if (--cbo == llength(clp)) /* end of line */
c = '\n';
else
c = lgetc(clp,cbo); /* somewhere in middle */
/* Check for a matching character. If still in a nested */
/* level, pop out of it and continue search. This check */
/* is done before the nesting check so single-character */
/* matches will work too. */
if (c == lbal) {
if (depth == 0) {
displaymatch(clp,cbo);
return (TRUE);
}
else
depth--;
}
/* Check for another level of nesting. */
if (c == rbal)
depth++;
}
/*NOTREACHED*/
}
/*
* Display matching character.
* Matching characters that are not in the current window
* are displayed in the echo line. If in the current
* window, move dot to the matching character,
* sit there a while, then move back.
*/
static displaymatch(clp, cbo)
register LINE *clp;
register int cbo;
{
register LINE *tlp;
register int tbo;
register int cp;
register int bufo;
register int c;
int inwindow;
char buf[NLINE];
/* Figure out if matching char is in current window by */
/* searching from the top of the window to dot. */
inwindow = FALSE;
for (tlp = curwp->w_linep; tlp != lforw(curwp->w_dotp); tlp = lforw(tlp))
if (tlp == clp)
inwindow = TRUE;
if (inwindow == TRUE) {
tlp = curwp->w_dotp; /* save current position */
tbo = curwp->w_doto;
curwp->w_dotp = clp; /* move to new position */
curwp->w_doto = cbo;
curwp->w_flag |= WFMOVE;
update(); /* show match */
sleep(1); /* wait a bit */
curwp->w_dotp = tlp; /* return to old position */
curwp->w_doto = tbo;
curwp->w_flag |= WFMOVE;
update();
}
else { /* match not in this window so display line in echo area */
bufo = 0;
for (cp = 0; cp < llength(clp); cp++) { /* expand tabs */
c = lgetc(clp,cp);
if (
#ifdef NOTAB
(mode&MNOTAB) ||
#endif
c != '\t')
if(ISCTRL(c)) {
buf[bufo++] = '^';
buf[bufo++] = c ^ 0x40;
} else buf[bufo++] = c;
else
do {
buf[bufo++] = ' ';
} while (bufo & 7);
}
buf[bufo++] = '\0';
ewprintf("Matches %s",buf);
}
return (TRUE);
}